<?php


namespace app\api\model;


use app\common\library\IDMan;
use app\common\library\StatModel;
use app\common\library\UMaleModel;
use app\common\model\BaseModel;
use common;
use ApiOper;
use think\Db;
use hiredis;

class ReparkOrderModel extends BaseModel
{
    protected $name = 'bike_repark_order';
    protected $pk = 'id';

    function submit($city_id, $bike_info, $bluetooth, $unlock)
    {
        if (empty($bike_info['bluetooth_token'])) {
            $bluetooth = 0;
        }

        if ($bike_info['bus_state'] != 0) {
            if ($bike_info['bus_state'] == BIKE_BUS_STAT_OPER_REPARK) {
                return [USR_ORDER_ERROR_BIKE_BUSY, " 车辆挪车中!"];
            } else if ($bike_info['bus_state'] == BIKE_BUS_STAT_BATTERY_CHANGE) {
                return [USR_ORDER_ERROR_BIKE_BUSY, " 车辆换电中!"];
            } else if ($bike_info['bus_state'] == BIKE_BUS_STAT_USER_REPARK) {
                return [USR_ORDER_ERROR_BIKE_BUSY, " 车辆挪车中!"];
            }
            else {
                return [USR_ORDER_ERROR_BIKE_BUSY, " 车辆骑行中!"];
            }
        }

        $ID = IDMan::city_order_id($city_id);
        $order_state = REPARK_ORDER_STATE_SUBMIT;
        $start_park_id = null;
        $start_park_name = null;

        $start_grade = 0;
        if (!empty($bike_info['park_id'])) {
            $parkinfo = (new ParkModel())->info($city_id, $bike_info['park_id']);
            $start_grade = $parkinfo['grade'];
        }
        $start_time = date('Y-m-d H:i:s');

        $usrinfo = ApiOper::instance()->_user_info;
        $order_info = [
            'id' => $ID,
            'city_id' => $city_id,
            'user_id' => $usrinfo['id'],
            'user_name' => $usrinfo['name'],
            'user_phone' => $usrinfo['phone'],
            'bike_id' => $bike_info['id'],
            'bike_sn' => $bike_info['sn'],
            'imei' => $bike_info['imei'],
            'order_state' => $order_state,
            'start_time' => $start_time,
            'start_park_state' => $bike_info['park_state'],
            'start_coordinate' => $bike_info['coordinate'],
            'start_address' => $bike_info['address'],
            'start_park_id' => $bike_info['park_id'],
            'start_park_name' => $bike_info['park_name'],
            'start_npa_id' => $bike_info['npa_id'],
            'start_npa_name' => $bike_info['npa_name'],
            'start_svca_id' => $bike_info['svca_id'],
            'start_svca_name' => $bike_info['svca_name'],
            'create_time' => date('Y-m-d H:i:s'),
            'channel' => ApiOper::instance()->userinfo()['channel'],
            'track' => [
                [
                    $bike_info['coordinate'][0],
                    $bike_info['coordinate'][1],
                    date('Y-m-d H:i:s'),
                    $bike_info['speed'],
                    $bike_info['course'],
                ],
            ],
            'start_grade' => $start_grade,
            'repark_index' => $bike_info['repark_index'],
        ];

        if (!empty(ApiOper::instance()->userinfo()['user_coordinate'])) {
            $order_info['user_start_coordinate'] = ApiOper::instance()->userinfo()['user_coordinate'];
        }

        (new BikeMgr())->oper_repark_start($city_id, $bike_info['id'], $order_info, $bluetooth, $unlock);

        self::create($order_info);

        if ($city_id == '451100'){
            (new UMaleModel())->bike_postInfo($bike_info,1);
        }

        return [0, '', $order_info];
    }

    function append_track($city_id, $order_id, $item)
    {
        $st = "update tb_bike_repark_order set track = " . hisql::json_append_array_s('track', $item) . " where city_id = ? and id = ?";
        $beans = [$city_id, $order_id];
        hisql::db()->execute($st, $beans);
    }

    function query_distance($city_id, $order_id, $park_id, $bluetooth)
    {
        $order_info = $this->query_info($city_id, $order_id);
        if (empty($order_info)) {
            return [ERROR_QUERY_INFO, "finish order get order info error!"];
        }

        if ($order_info['order_state'] == REPARK_ORDER_STATE_FINISHED) {
            return [ERROR_STATE_DISMATCH, "order_state = " . $order_info['order_state']];
        }

        $bike_info = (new BikeModel())->get_info_by_id($order_info['bike_id']);
        if (empty($bike_info)) {
            //订单异常
            $data = [
                'order_state' => -1,
            ];
            $where = [
                'city_id' => $city_id,
                'id' => $order_id,
            ];

            self::update($data, $where);
            return [ERROR_QUERY_INFO, "查询车辆信息失败！"];
        }

        if (empty($bike_info['bluetooth_token'])) {
            $bluetooth = 0;
        }

        $park = null;
        $toofar = false;
        if ($park_id) {
            $park = (new ParkModel())->info($city_id, $park_id);
            if (empty($park)) {
                return [X_ERROR, "获取车站信息失败！"];
            }
            $distance = common::distance($park['coordinate'], $bike_info['coordinate']);
            if (($bike_info['park_state'] != BIKE_PARK_STAT_OSA && $bike_info['park_state'] != BIKE_PARK_STAT_NPA) && ($distance > $park['radius']+10)) {
                $toofar = true;
                if (!empty(ApiOper::instance()->userinfo()['user_coordinate'])) {
                    $distance_oper = common::distance($park['coordinate'], ApiOper::instance()->userinfo()['user_coordinate']);
                    if ($distance_oper < $park['radius']) {
                        $toofar = false;
                    }
                    $distance = min($distance_oper, $distance);
                }
            }

            if ($toofar) {
                if (time() - strtotime($bike_info['gps_update_time']) < 30) {
                    return [0, "距离车站太远，{$distance}米,是否确定挪车？",$order_info];
                }
            }
        } else {
            $park = (new ParkModel())->is_in($city_id, $bike_info['coordinate']);
        }

        $bound_order_info = [
            'order_type' => ORDER_TYPE_BIKE_REPARK,
            'order_id' => $order_info['id'],
            'op' => '结束挪车',
        ];

        if ($bike_info['is_defend_on'] == 0 && $bike_info['last_repark_order_id'] == $order_id) {
            if ($bike_info['last_repark_order_id'] == $order_id) {
                if (!$bluetooth) {
                    $ret = (new BikeMgr())->lock($city_id, $order_info['bike_id'], $bound_order_info);
                    if ($ret[0] != 0) {
                        //throw_myexception(X_ERROR, "锁车失败，错误信息：" . $ret[1] . "，请重试！");
                    }
                }
            }
        }

        $bike_info = BikeModel::instance()->get_info_by_id($order_info['bike_id']);

        $now = date('Y-m-d H:i:s');

        $park_state_info = [
            'park_state' => BIKE_PARK_STAT_FREE,
            'park_update_time' => date('Y-m-d H:i:s'),
        ];

        $service_area_info = (new ServiceAreaModel())->is_in($city_id, $bike_info['coordinate']);
        if (empty($service_area_info)) {
            $park_state_info['svca_id'] = null;
            $park_state_info['svca_name'] = null;
            $park_state_info['park_state'] = BIKE_PARK_STAT_OSA;
        } else {
            $park_state_info['svca_id'] = $service_area_info['id'];
            $park_state_info['svca_name'] = $service_area_info['name'];
        }

        $no_parking_area_info = (new NPAModel())->is_in($city_id, $bike_info['coordinate']);
        if (!empty($no_parking_area_info)) {
            $park_state_info['park_state'] = BIKE_PARK_STAT_NPA;
            $park_state_info['npa_id'] = $no_parking_area_info['id'];
            $park_state_info['npa_name'] = $no_parking_area_info['name'];
        } else {
            $park_state_info['npa_id'] = null;
            $park_state_info['npa_name'] = null;
        }

        $grade = 100;
        $end_grade = 0;
        $grade_info = [];
        if (!empty($park))
        {
            $park_state_info['park_state'] = BIKE_PARK_STAT_PARK;
            $park_state_info['park_id'] = $park['id'];
            $park_state_info['park_name'] = $park['name'];
            $end_grade = empty($park) ? 0 : $park['grade'];
            if ($park['bike_count'] < $park['capacity']) {
                $grade = 100;
            } else {
                $grade = 0;
                $grade_info['remark'] = "车站供给过量,[" . $park['bike_count'] . "," . $park['capacity'] . ']！';
            }
        }
        else
        {
            $park_state_info['park_id'] = null;
            $park_state_info['park_name'] = null;
            $grade_info['remark'] = '未挪至车站！';
            $grade = 0;
        }

        if ($order_info['start_park_state'] == BIKE_PARK_STAT_PARK) {
            $grade = 0;
            $grade_info['remark'] = '车辆起始点为车站';
        }

        if ($order_info['repark_index'] == 0) {
            $grade = 0;
            $grade_info['remark'] = '非差车挪车';
        }

        $item = [
            floatval($bike_info['coordinate'][0]),
            floatval($bike_info['coordinate'][1]),
            date('Y-m-d H:i:s'),
            intval($bike_info['speed']),
            intval($bike_info['course']),
        ];

        $this->append_track($city_id, $order_id, $item);
        $track = $order_info['track'];
        $track[] = $item;

        $duration = time() - strtotime($order_info['start_time']);
        $distance = $this->calc_miles($track);
        if ($distance < 150) {
            if (empty($park_state_info['park_id'])){
                $grade = 0;
                $grade_info['remark'] = '未挪进站点';
            }else if ($park_state_info['park_id'] == $order_info['start_park_id']) {
                $grade = 0;
                $grade_info['remark'] = '站内无需挪车';
            }
            else
            {
                if($toofar)
                {
                    $grade = 0;
                    $grade_info['remark'] = '挪车距离过短,是否需要挪车';
                }
            }
        }

        if ($duration<60){
            $grade = 0;
            $grade_info['remark'] = '挪车时间小于1分钟';
        }

        //禁停区、服务区外挪车均为有效（不判断时间距离）
        if($order_info['start_park_state'] == BIKE_PARK_STAT_NPA || $order_info['start_park_state'] == BIKE_PARK_STAT_OSA){
            if(!empty($park_state_info)&&($park_state_info['park_state'] == BIKE_PARK_STAT_PARK)){
                $grade = 100;
                $grade_info['remark'] = null;
            }
        }

        $grade_info['start_grade'] = $order_info['start_grade'];
        $grade_info['end_grade'] = $order_info['end_grade'];
        $grade_info['grade'] = $order_info['grade'];

        $data = [
            'order_state' => REPARK_ORDER_STATE_FINISHED,
            'end_time' => $now,
            'end_coordinate' => json_encode($bike_info['coordinate']),
            'end_address' => $bike_info['address'],
            'track' => json_encode($track),
            'duration' => time() - strtotime($order_info['start_time']),
            'distance' => $distance,
            'end_park_state' => $park_state_info['park_state'],
            'end_park_id' => $park_state_info['park_id'],
            'end_park_name' => $park_state_info['park_name'],
            'end_npa_id' => $park_state_info['npa_id'],
            'end_npa_name' => $park_state_info['npa_name'],
            'end_svca_id' => $park_state_info['svca_id'],
            'end_svca_name' => $park_state_info['npa_name'],
            'end_grade' => $end_grade,
            'grade' => $grade,
            'grade_info' => $grade_info,
        ];

        if (!empty(ApiOper::instance()->userinfo()['user_coordinate'])) {
            $data['user_end_coordinate'] = ApiOper::instance()->userinfo()['user_coordinate'];
        }
        $where = [
            'city_id' => $city_id,
            'id' => $order_id,
        ];

        self::update( $data, $where);

        (new BikeMgr())->oper_repark_finish($city_id, $bike_info['id'], $park_state_info);

        $this->stats_add($city_id, $order_info['user_id'], $grade);

        if ($bike_info['is_defend_on'] == 0 && $bike_info['last_repark_order_id'] == $order_id) {
            if ($bike_info['last_repark_order_id'] == $order_id) {
                if (!$bluetooth) {
                    // (new BikeMgr())->asyn_lock($city_id, $bike_info['id'], $bound_order_info, 5);
                    (new BikeMgr())->asyn_check_defend_state($bike_info['id']);
                }
            }
        }


        (new BikeMgr())->asyn_update_bluetooth($bike_info);


        //更新记录
        $com_info =[
            'bike_sn' => $bike_info['sn'],
            'com_staff_type' => OPER_TYPE_OPS,
            'com_staff_id'   => $order_info['user_id'],
            'com_staff_name'   => $order_info['user_name'],
        ];

        (new BikeMgr())->asyn_warn_info($com_info);

        (new StatModel())->ops_month_repark_incr($city_id, $order_info['user_name'], 1);

        (new StatNewModel())->repark_incr($city_id, $grade);

        return [0, '', array_merge($order_info, $data)];
    }


    function finish($city_id, $order_id, $park_id, $bluetooth)
    {
        $order_info = $this->query_info($city_id, $order_id);
        if (empty($order_info)) {
            return [ERROR_QUERY_INFO, "finish order get order info error!"];
        }

        if ($order_info['order_state'] == REPARK_ORDER_STATE_FINISHED) {
            return [ERROR_STATE_DISMATCH, "order_state = " . $order_info['order_state']];
        }

        $bike_info = (new BikeModel())->get_info_by_sn($order_info['bike_sn']);
        if (empty($bike_info)) {
            //订单异常
            $data = [
                'order_state' => -1,
            ];
            $where = [
                'city_id' => $city_id,
                'id' => $order_id,
            ];

            self::update($data, $where);
            return [ERROR_QUERY_INFO, "查询车辆信息失败！"];
        }

        if (empty($bike_info['bluetooth_token'])) {
            $bluetooth = 0;
        }

        $park = null;
        $toofar = false;
        if (time() - strtotime($bike_info['gps_update_time']) > 30) {
            $n = (new BikeMgr())->query_bike_info_rt($bike_info['imei']);
            if($n){
                $bike_info = (new BikeModel())->get_info_by_sn($order_info['bike_sn']);
            }
        }
        if ($park_id) {
            $park = (new ParkModel())->info($city_id, $park_id);
            if (empty($park)) {
                return [X_ERROR, "获取车站信息失败！"];
            }
            $distance = common::distance($park['coordinate'], $bike_info['coordinate']);
            if (($bike_info['park_state'] != BIKE_PARK_STAT_OSA && $bike_info['park_state'] != BIKE_PARK_STAT_NPA) && ($distance > $park['radius']+10)) {
                $toofar = true;
                if (!empty(ApiOper::instance()->userinfo()['user_coordinate'])) {
                    $distance_oper = common::distance($park['coordinate'], ApiOper::instance()->userinfo()['user_coordinate']);
                    if ($distance_oper < $park['radius']) {
                        $toofar = false;
                    }
                    $distance = min($distance_oper, $distance);
                }
            }

            if ($toofar) {
                $park = null;
//                if (time() - strtotime($bike_info['gps_update_time']) < 30) {
//                    return [X_ERROR, "距离车站太远，{$distance}米！"];
//                }
            }
        } else {
            $park = (new ParkModel())->is_in($city_id, $bike_info['coordinate']);
        }

        $bound_order_info = [
            'order_type' => ORDER_TYPE_BIKE_REPARK,
            'order_id' => $order_info['id'],
            'op' => '结束挪车',
        ];

        if ($bike_info['is_defend_on'] == 0 && $bike_info['last_repark_order_id'] == $order_id) {
            if ($bike_info['last_repark_order_id'] == $order_id) {
                if (!$bluetooth) {
                    $ret = (new BikeMgr())->lock($city_id, $order_info['bike_id'], $bound_order_info);
                    if ($ret[0] != 0) {
                        //throw_myexception(X_ERROR, "锁车失败，错误信息：" . $ret[1] . "，请重试！");
                    }
                }
            }
        }

        $bike_info = BikeModel::instance()->get_info_by_sn($order_info['bike_sn']);

        $now = date('Y-m-d H:i:s');

        $park_state_info = [
            'park_state' => BIKE_PARK_STAT_FREE,
            'park_update_time' => date('Y-m-d H:i:s'),
        ];

        $service_area_info = (new ServiceAreaModel())->is_in($city_id, $bike_info['coordinate']);
        if (empty($service_area_info)) {
            $park_state_info['svca_id'] = null;
            $park_state_info['svca_name'] = null;
            $park_state_info['park_state'] = BIKE_PARK_STAT_OSA;
        } else {
            $park_state_info['svca_id'] = $service_area_info['id'];
            $park_state_info['svca_name'] = $service_area_info['name'];
        }

        $no_parking_area_info = (new NPAModel())->is_in($city_id, $bike_info['coordinate']);
        if (!empty($no_parking_area_info)) {
            $park_state_info['park_state'] = BIKE_PARK_STAT_NPA;
            $park_state_info['npa_id'] = $no_parking_area_info['id'];
            $park_state_info['npa_name'] = $no_parking_area_info['name'];
        } else {
            $park_state_info['npa_id'] = null;
            $park_state_info['npa_name'] = null;
        }

        $grade = 100;
        $end_grade = 0;
        $grade_info = [];
        if (!empty($park)) {
            $park_state_info['park_state'] = BIKE_PARK_STAT_PARK;
            $park_state_info['park_id'] = $park['id'];
            $park_state_info['park_name'] = $park['name'];
            $end_grade = empty($park) ? 0 : $park['grade'];
            if ($park['bike_count'] < $park['capacity']) {
                $grade = 100;
            } else {
                $grade = 0;
                $grade_info['remark'] = "车站供给过量,[" . $park['bike_count'] . "," . $park['capacity'] . ']！';
            }
        } else {
            $park_state_info['park_id'] = null;
            $park_state_info['park_name'] = null;
            $grade_info['remark'] = '未挪至车站！';
            $grade = 0;
        }
        if ($order_info['start_park_state'] == BIKE_PARK_STAT_PARK) {
            $grade = 0;
            $grade_info['remark'] = '车辆起始点为车站';
        }
        if ($order_info['repark_index'] == 0) {
            $grade = 0;
            $grade_info['remark'] = '非差车挪车';
        }
        $item = [
            floatval($bike_info['coordinate'][0]),
            floatval($bike_info['coordinate'][1]),
            date('Y-m-d H:i:s'),
            intval($bike_info['speed']),
            intval($bike_info['course']),
        ];

        $this->append_track($city_id, $order_id, $item);
        $track = $order_info['track'];
        $track[] = $item;

        $duration = time() - strtotime($order_info['start_time']);
        $distance = $this->calc_miles($track);
        if ($distance < 150) {
            if (empty($park_state_info['park_id'])){
                $grade = 0;
                $grade_info['remark'] = '未挪进站点';
            }else if ($park_state_info['park_id'] == $order_info['start_park_id']) {
                $grade = 0;
                $grade_info['remark'] = '站内无需挪车';
            }
            else
            {
                if($toofar)
                {
                    $grade = 0;
                    $grade_info['remark'] = '挪车距离过短,是否需要挪车';
                }
            }
        }

        if ($duration<60){
            $grade = 0;
            $grade_info['remark'] = '挪车时间小于1分钟';
        }


        //禁停区、服务区外挪车均为有效（不判断时间距离）
        if($order_info['start_park_state'] == BIKE_PARK_STAT_NPA || $order_info['start_park_state'] == BIKE_PARK_STAT_OSA){
            if(!empty($park_state_info)&&($park_state_info['park_state'] == BIKE_PARK_STAT_PARK)){
                $grade = 100;
                $grade_info['remark'] = null;
            }
        }


        $grade_info['start_grade'] = $order_info['start_grade'];
        $grade_info['end_grade'] = $order_info['end_grade'];
        $grade_info['grade'] = $order_info['grade'];
        //$grade_info['start_heat'] = (new OrderDistMap())->heat($city_id, $order_info['start_coordinate']);
        //$grade_info['end_heat'] = (new OrderDistMap())->heat($city_id, $bike_info['coordinate']);
        $data = [
            'order_state' => REPARK_ORDER_STATE_FINISHED,
            'end_time' => $now,
            'end_coordinate' => json_encode($bike_info['coordinate']),
            'end_address' => $bike_info['address'],
            'track' => json_encode($track),
            'duration' => time() - strtotime($order_info['start_time']),
            'distance' => $distance,
            'end_park_state' => $park_state_info['park_state'],
            'end_park_id' => $park_state_info['park_id'],
            'end_park_name' => $park_state_info['park_name'],
            'end_npa_id' => $park_state_info['npa_id'],
            'end_npa_name' => $park_state_info['npa_name'],
            'end_svca_id' => $park_state_info['svca_id'],
            'end_svca_name' => $park_state_info['npa_name'],
            'end_grade' => $end_grade,
            'grade' => $grade,
            'grade_info' => $grade_info,
        ];

        if (!empty(ApiOper::instance()->userinfo()['user_coordinate'])) {
            $data['user_end_coordinate'] = ApiOper::instance()->userinfo()['user_coordinate'];
        }
        $where = [
            'city_id' => $city_id,
            'id' => $order_id,
        ];

        self::update($data, $where);

        (new BikeMgr())->oper_repark_finish($city_id, $bike_info['id'], $park_state_info);

        $this->stats_add($city_id, $order_info['user_id'], $grade);

        if ($bike_info['is_defend_on'] == 0 && $bike_info['last_repark_order_id'] == $order_id) {
            if ($bike_info['last_repark_order_id'] == $order_id) {
                if (!$bluetooth) {
                    // (new BikeMgr())->asyn_lock($city_id, $bike_info['id'], $bound_order_info, 5);
                    (new BikeMgr())->asyn_check_defend_state($bike_info['id']);
                }
            }
        }


        (new BikeMgr())->asyn_update_bluetooth($bike_info);

        //更新记录
        $com_info =[
            'bike_sn' => $bike_info['sn'],
            'com_staff_type' => OPER_TYPE_OPS,
            'com_staff_id'   => $order_info['user_id'],
            'com_staff_name'   => $order_info['user_name'],
        ];

        (new BikeMgr())->asyn_warn_info($com_info);

        (new StatModel())->ops_month_repark_incr($city_id, $order_info['user_name'], 1);
        (new StatNewModel())->repark_incr($city_id, $grade);

        if ($city_id == '451100'){
            (new UMaleModel())->bike_postInfo($bike_info,0);
        }

        return [0, '', array_merge($order_info, $data)];
    }

    function query_info($city_id, $order_id)
    {
        $selectlist = [
            'id' => 'string',
            'city_id' => 'string',
            'user_id' => 'string',
            'user_name' => 'string',
            'user_phone' => 'string',
            'bike_id' => 'string',
            'bike_sn' => 'string',
            'imei' => 'string',
            'order_state' => 'int',
            'start_time' => 'string',
            'start_coordinate' => 'array',
            'start_address' => 'string',
            'start_park_id' => 'string',
            'start_park_name' => 'string',
            'end_time' => 'string',
            'end_coordinate' => 'array',
            'end_address' => 'string',
            'end_park_id' => 'string',
            'end_park_name' => 'string',
            'track' => 'array',
            'distance' => 'int',
            'duration' => 'int',
            'create_time' => 'string',
            'user_start_coordinate' => 'array',
            'user_end_coordinate' => 'array',
            'start_park_state' => 'int',
            'end_park_state' => 'int',
            'grade' => 'int',
            'start_grade' => 'int',
            'end_grade' => 'int',
            'grade_info' => 'array',
            'repark_index' => 'int',
        ];

        $sfs = common::array_keys($selectlist);
        $beans = [
            'id'=>$order_id,
        ];

        if (!empty($city_id)) {
            $beans['city_id'] = $city_id;
        }

        return $this->where($beans)->field($sfs)->find();
    }

    function query_track($city_id, $order_id)
    {
        $selectlist = [
            'bike_sn' => 'string',
            'start_time' => 'string',
            'end_time' => 'string',
            'start_coordinate' => 'array',
            'end_coordinate' => 'array',
            'start_park_state' => 'int',
            'end_park_state' => 'int',
            'track' => 'array',
        ];

        $sfs = common::array_keys($selectlist);
        $beans = [
            'city_id'=>$city_id,
            'id'=>$order_id,
        ];
        return $this->where($beans)->field($sfs)->find();
    }

    function calc_miles($track)
    {
        $miles = 0;
        for ($i = 1; $i < count($track); $i++) {
            $c1 = [$track[$i - 1][0], $track[$i - 1][1]];
            $c2 = [$track[$i][0], $track[$i][1]];
            $miles += common::distance($c1, $c2);
        }
        return $miles;
    }

    function query_list($city_id, $condition, $pos, $limit)
    {
        $selectlist = [
            'id' => 'string',
            'city_id' => 'string',
            'user_id' => 'string',
            'user_name' => 'string',
            'user_phone' => 'string',
            'bike_id' => 'string',
            'bike_sn' => 'string',
            'imei' => 'string',
            'order_state' => 'int',
            'start_time' => 'string',
            'start_coordinate' => 'array',
            'start_address' => 'string',
            'start_park_id' => 'string',
            'start_park_name' => 'string',
            'end_time' => 'string',
            'end_coordinate' => 'array',
            'end_address' => 'string',
            'end_park_id' => 'string',
            'end_park_name' => 'string',
            // 'track' => 'array',
            'distance' => 'int',
            'duration' => 'int',
            'create_time' => 'string',
            'channel' => 'string',
            'start_park_state' => 'int',
            'end_park_state' => 'int',
            'grade' => 'int',
            'grade_info' => 'array',
            'repark_index' => 'int',
        ];
        $sfs = common::array_keys($selectlist);
        $beans = [
            'city_id'=>$city_id,
        ];

        if (isset($condition['is_start_from_park'])) {
            if ($condition['is_start_from_park']) {
                $beans['start_park_id'] = "not null";
            } else {
                $beans['start_park_id'] = "null";
            }
        }
        if (isset($condition['is_order_finished'])) {
            if ($condition['is_order_finished']) {
                $beans['order_state'] = REPARK_ORDER_STATE_FINISHED;
            } else {
                $beans['order_state'] = ['<',REPARK_ORDER_STATE_FINISHED];
            }
        }
        if (isset($condition['user_id'])) {
            $beans['user_id'] = $condition['user_id'];
        }
        if (isset($condition['start_park_state'])) {
            $beans['start_park_state'] = $condition['start_park_state'];
        }

        if (isset($condition['sk']) && !empty($condition['sk'])) {
            $sk = $condition['sk'];
            if (common::is_phone($sk)) {
                $beans['user_phone'] = $sk;
            } else if (IDMan::is_bike_sn($sk)) {
                $beans['bike_sn'] = $sk;
            } else if (common::is_name($sk)) {
                $beans['user_name'] = $sk;
            } else if (IDMan::is_bike_id($sk)) {
                $beans['bike_id'] = $sk;
            }
        }

        if (isset($condition['start_time'])) {
            $beans['create_time'] = ['>=',$condition['start_time']];
        }
        if (isset($condition['end_time'])) {
            $beans['create_time'] = ['<=',$condition['end_time']];
        }


        $rows = $this->where($beans)->field($sfs)->order('create_time','desc')->limit($pos,$limit)->select();
        return $rows->toArray();
    }

    function query_count()
    {
        return 100;
    }

    function stats_add($city_id, $user_id, $grade)
    {
        $key = 'REPARK_STATE|' . $city_id . '|' . $user_id;
        $info = [
            'total_count' => 0,
            'valid_count' => 0,
            'grade_sum' => 0,
        ];

        $day = date('Y-m-d');
        $val = hiredis::db()->hGet($key, $day);
        if (!empty($val)) {
            $info = json_decode($val, true);
        }

        $info['total_count']++;
        if ($grade > 0) {
            $info['valid_count']++;
            $info['grade_sum'] += $grade;
        }
        hiredis::db()->hSet($key, $day, json_encode($info));
    }

    function stats_month_query($city_id, $user_id)
    {

        $key = 'REPARK_STATE|' . $city_id . '|' . $user_id;
        $fileds[] = null;
        for ($i = 0; $i < 30; $i++) {
            $fileds[] = date('Y-m-d', strtotime("-{$i} day"));
        }

        $l = [];
        $kvs = hiredis::db()->hMget($key, $fileds);
        foreach ($kvs as $k => $v) {
            if (empty($v)) {
                $l[] = [
                    'total_count' => 0,
                    'valid_count' => 0,
                    'grade_sum' => 0,
                    'date' => $k
                ];
            } else {
                $info = json_decode($v, true);
                $info['date'] = $k;
                $l[] = $info;
            }
        }
        return $l;
    }


    //分析日志
    function analyz_month_date($city_id,$condition){

        $condition['is_order_finished'] = 1;
        $condition['user_id'] = ApiOper::instance()->userinfo()['id'];

        $list = $this->query_list($city_id,$condition,0,1000);

        $vaild = 0;
        $not_vaild = 0;
        foreach ($list as $val){
            if ($val['grade'] == 100){
                $vaild++;
            }
            else{
                $not_vaild++;
            }
        }

        return [$vaild,$not_vaild,count($list)];
    }

    //分析 $user_phone = 1 ,0姓名 2:id ,$vaild = 1
    function analyze($city_id,$condition,$use_phone = 1,$vaild = 0){
        $condition['is_order_finished'] = 1;

        $list = $this->query_list($city_id,$condition,0,5000);

        $repark_list =[];

        if ($use_phone == 1){
            foreach ($list as $val){
                if (!isset($repark_list[$val['user_phone']])){
                    $repark_list[$val['user_phone']] = 0;
                }

                if ($vaild == 1)
                {
                    if ($val['grade'] == 100)
                    {
                        $repark_list[$val['user_phone']]++;
                    }
                }
                else
                    $repark_list[$val['user_phone']]++;

            }
        }
        else if ($use_phone == 2){
            foreach ($list as $val){
                if (!isset($repark_list[$val['user_id']])){
                    $repark_list[$val['user_id']] = 0;
                }

                if ($vaild == 1)
                {
                    if ($val['grade'] == 100)
                    {
                        $repark_list[$val['user_id']]++;
                    }
                }
                else
                    $repark_list[$val['user_id']]++;
            }
        }
        else {
            foreach ($list as $val){
                if (!isset($repark_list[$val['user_name']])){
                    $repark_list[$val['user_name']] = 0;
                }

                if ($vaild == 1)
                {
                    if ($val['grade'] == 100)
                    {
                        $repark_list[$val['user_name']]++;
                    }
                }
                else
                    $repark_list[$val['user_name']]++;
            }
        }


        return $repark_list;
    }
}